using System;
using System.IO;
using System.Numerics;
using OracleInternal.Json.Common;
using OracleInternal.Json.Sql;

namespace OracleInternal.Json.Binary
{
	internal class OsonGenerator : OracleJsonGenerator
	{
		private OsonGeneratorState m_state;

		internal OsonGenerator(OsonGeneratorStatePool pool, Stream outStream)
		{
			if (pool != null)
			{
				m_state = pool.GetState(outStream);
			}
			else
			{
				m_state = new OsonGeneratorState(null, outStream);
			}
		}

		public void Reset(Stream outStream)
		{
			m_state.Reset(outStream);
		}

		public void SetTinyNodeStat(bool nodeValue)
		{
			m_state.m_writeTinyNodeCount = nodeValue;
		}

		public override IOracleJsonGenerator WriteStartObject()
		{
			m_state.WriteStartObject();
			return this;
		}

		public override IOracleJsonGenerator WriteKey(string key)
		{
			m_state.WriteKey(key);
			return this;
		}

		public override IOracleJsonGenerator WriteStartArray()
		{
			m_state.WriteStartArray();
			return this;
		}

		public override IOracleJsonGenerator WriteEnd()
		{
			m_state.WriteEnd();
			return this;
		}

		public override IOracleJsonGenerator Write(string value)
		{
			m_state.WriteString(value);
			return this;
		}

		public override IOracleJsonGenerator Write(char[] value, int strLen)
		{
			m_state.WriteString(new string(value, 0, strLen));
			return this;
		}

		public override IOracleJsonGenerator Write(decimal value)
		{
			m_state.WriteDecimal(value);
			return this;
		}

		public override IOracleJsonGenerator Write(BigInteger value)
		{
			m_state.WriteDecimal(value);
			return this;
		}

		public override IOracleJsonGenerator Write(int value)
		{
			m_state.WriteSB4(value);
			return this;
		}

		public override IOracleJsonGenerator Write(long value)
		{
			m_state.WriteSB8(value);
			return this;
		}

		public override IOracleJsonGenerator Write(double value)
		{
			m_state.WriteDouble(value);
			return this;
		}

		public override IOracleJsonGenerator Write(bool value)
		{
			m_state.WriteBoolean(value);
			return this;
		}

		public override IOracleJsonGenerator WriteNull()
		{
			m_state.AddOp(48);
			m_state.m_ctx.Primitive();
			return this;
		}

		public override void Close()
		{
			if (m_state != null)
			{
				m_state.Close();
				if (m_state.m_pool != null)
				{
					m_state.m_pool.PutState(m_state);
				}
				m_state = null;
			}
		}

		public override IOracleJsonGenerator Write(string key, byte[] value)
		{
			WriteKey(key);
			Write(value);
			return this;
		}

		public override IOracleJsonGenerator Write(string key, DateTime value)
		{
			WriteKey(key);
			Write(value);
			return this;
		}

		public override IOracleJsonGenerator Write(byte[] bytes)
		{
			m_state.WriteBytes(bytes);
			return this;
		}

		public override IOracleJsonGenerator WriteId(byte[] bytes)
		{
			m_state.WriteId(bytes);
			return this;
		}

		public override IOracleJsonGenerator Write(DateTime instant)
		{
			byte[] raw = OsonPrimitiveConversions.DateTimeToTimestamp(m_state.GetExceptionFactory(), instant);
			m_state.WriteTimestamp(raw);
			return this;
		}

		public override IOracleJsonGenerator Write(float value)
		{
			m_state.WriteFloat(value);
			return this;
		}

		public IOracleJsonGenerator WriteDate(DateTime instant)
		{
			byte[] raw = OsonPrimitiveConversions.DateTimeToDate(m_state.GetExceptionFactory(), instant);
			m_state.WriteDate(raw);
			return this;
		}

		public IOracleJsonGenerator WriteIntervalDS(TimeSpan value)
		{
			byte[] raw = OsonPrimitiveConversions.DurationToIntervalDS(value);
			m_state.WriteIntervalDS(raw);
			return this;
		}

		internal IOracleJsonGenerator WriteIntervalYM(Period value)
		{
			byte[] raw = OsonPrimitiveConversions.PeriodToIntervalYM(m_state.GetExceptionFactory(), value);
			m_state.WriteIntervalYM(raw);
			return this;
		}

		public IOracleJsonGenerator WriteNumberAsString(decimal bd)
		{
			m_state.WriteNumberAsString(bd);
			return this;
		}

		protected override IOracleJsonGenerator WriteBinary(OracleJsonBinary value)
		{
			byte[] bytes = value.GetBytes();
			if (value.IsId())
			{
				m_state.WriteId(bytes);
			}
			else
			{
				m_state.WriteBytes(bytes);
			}
			return this;
		}

		protected override IOracleJsonGenerator WriteDouble(OracleJsonDouble value)
		{
			return Write(value.DoubleValue());
		}

		protected override IOracleJsonGenerator WriteFloat(OracleJsonFloat value)
		{
			return Write(value.FloatValue());
		}

		public void WriteDecimal(decimal value)
		{
			m_state.WriteDecimal(value);
		}

		public void WriteSB4(int value)
		{
			m_state.WriteSB4(value);
		}

		public void WriteSB8(long value)
		{
			m_state.WriteSB8(value);
		}

		protected override IOracleJsonGenerator WriteOraNumber(OracleJsonDecimal value)
		{
			m_state.WriteOraNumber(value);
			return this;
		}

		protected override IOracleJsonGenerator WriteTimestamp(OracleJsonTimestamp value)
		{
			m_state.WriteTimestamp(value.Raw());
			return this;
		}

		protected override IOracleJsonGenerator WriteTimestampTZ(OracleJsonTimestampTZ value)
		{
			m_state.WriteTimestamp(value.Raw());
			return this;
		}

		protected override IOracleJsonGenerator WriteDate(OracleJsonDate value)
		{
			m_state.WriteDate(value.Raw());
			return this;
		}

		protected override IOracleJsonGenerator WriteIntervalDS(OracleJsonIntervalDS value)
		{
			m_state.WriteIntervalDS(value.Raw());
			return this;
		}

		protected override IOracleJsonGenerator WriteIntervalYM(OracleJsonIntervalYM value)
		{
			m_state.WriteIntervalYM(value.Raw());
			return this;
		}

		protected override IOracleJsonGenerator WriteString(OracleJsonString value)
		{
			return Write(value.GetJsonString());
		}

		public override void Flush()
		{
		}

		public override IOracleJsonGenerator Write(Period p)
		{
			m_state.WriteIntervalYM(OsonPrimitiveConversions.PeriodToIntervalYM(m_state.GetExceptionFactory(), p));
			return this;
		}

		public override IOracleJsonGenerator Write(TimeSpan d)
		{
			m_state.WriteIntervalDS(OsonPrimitiveConversions.DurationToIntervalDS(d));
			return this;
		}
	}
}
